﻿using MediaLib.Implement;
using OpenGLLib;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
//using OpenTK.Wpf;

namespace FFmepgWpf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MahApps.Metro.Controls.MetroWindow
    {
        private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

        public IntPtr win32Ptr;

        public MainWindow()
        {
            InitializeComponent();
            //GLWpfControlSettings settings = new GLWpfControlSettings
            //{
            //    MajorVersion = 3,
            //    MinorVersion = 3
            //};
            //glCtl.Start(settings);
        }

        private unsafe void WinLoaded(object sender, RoutedEventArgs e)
        {
            WindowInteropHelper winInterop = new WindowInteropHelper(this);
            win32Ptr = winInterop.Handle;

            FFmpegLib.FFmpegUtils.DebugLog += FFLog;
            FFmpegLib.FFmpegUtils.FFmpegLibInit();

        }

        private void WinUnloaded(object sender, RoutedEventArgs e)
        {
            FFmpegLib.FFmpegUtils.DebugLog -= FFLog;
        }

        private void AudioPlayerClick(object sender, RoutedEventArgs e)
        {
            AudioPlayerWin win = new AudioPlayerWin();
            win.ShowDialog();
        }

        private unsafe void MediaPlayerClick(object sender, RoutedEventArgs e)
        {
            mediaFile = null;
            Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
            dialog.Filter = "视频文件|*.mp4;*.avi;*.flv;*.rmvb;|全部文件|*.*;";
            bool? openRs = dialog.ShowDialog();
            if (openRs.HasValue && openRs.Value)
                mediaFile = dialog.FileName;
            else
                return;

            if (!System.IO.File.Exists(mediaFile))
            {
                MessageBox.Show($"文件不存在:({mediaFile})", "提示", MessageBoxButton.OK);
            }

            //LoadOpenGLWin(meidaFile);
            LoadSDLWin(mediaFile);
            //LoadGlfwWin();
        }

        #region Silk.NET.SDL
        private string mediaFile = null;
        private unsafe void LoadSDLWin(string meidaFile)
        {
            silkMP = new SilkMediaPlayer(meidaFile);
            silkMP.Open();
            silkMP.VideoPlayAction += SdlDisplayYuv;
            silkMP.Play();
        }

        SilkSDLUtils silkSDL;
        SilkMediaPlayer silkMP;

        private unsafe void SdlDisplayYuv(FFmpegLib.FAVFrame frame)
        {
            Dispatcher.Invoke(() =>
            {
                try
                {
                    if (silkSDL == null)
                    {
                        silkSDL = new SilkSDLUtils();
                        bool rs = silkSDL.CreateWin(frame.Width, frame.Height, mediaFile);
                        silkSDL.Show();
                    }
                    if (silkSDL.Disposed)
                    {
                        silkMP.PlayStatus = Silk.NET.OpenAL.SourceState.Stopped;
                        return;
                    }
                    silkSDL.UpdateYuv(frame.Ptr->data.ToArray(), frame.Ptr->linesize.ToArray());
                }
                catch { }
            });
        }
        #endregion

        #region Silk.NET.OpenGL
        private unsafe void LoadOpenGLWin(string meidaFile)
        {
            opengl = new SilkOpenGLESUtils();
            opengl.CreateWin();

            Task.Factory.StartNew(() =>
           {
               silkMP = new SilkMediaPlayer(meidaFile);
               silkMP.Open();
               silkMP.VideoPlayAction += OpenGLDisplay;
               silkMP.Play();
           });
            opengl.Show();
        }
        SilkOpenGLESUtils opengl;

        private unsafe void OpenGLDisplay(FFmpegLib.FAVFrame frame)
        {
            Dispatcher.Invoke(() =>
            {
                opengl?.UpdateYuv(frame.Ptr->data.ToArray(), frame.Ptr->linesize.ToArray());
            });
        }
        #endregion

        #region Silk.NET.GLFW.Glfw
        private unsafe void LoadGlfwWin()
        {
            //Silk.NET.Core.Contexts.INativeContext context = Silk.NET.GLFW.Glfw.CreateDefaultContext(null);
            Silk.NET.GLFW.Glfw glfw = Silk.NET.GLFW.Glfw.GetApi();
            glfw.Init();
            glfw.WindowHint(Silk.NET.GLFW.WindowHintInt.ContextVersionMajor, 3);
            glfw.WindowHint(Silk.NET.GLFW.WindowHintInt.ContextVersionMinor, 3);
            glfw.WindowHint(Silk.NET.GLFW.WindowHintOpenGlProfile.OpenGlProfile, Silk.NET.GLFW.OpenGlProfile.Core);

            Silk.NET.GLFW.WindowHandle* winHandle = glfw.CreateWindow(1280, 720, "Glfw窗口", null, null);
            if (winHandle == null) return;

            glfw.MakeContextCurrent(winHandle);

            Silk.NET.Core.Contexts.INativeContext glCtx = Silk.NET.OpenGLES.GL.CreateDefaultContext(new string[1] { "default" }); // new string[1] { "default" }
            Silk.NET.OpenGLES.GL gl = Silk.NET.OpenGLES.GL.GetApi(glCtx);
            gl.Viewport(0, 0, 1280u, 720u);

            while (!glfw.WindowShouldClose(winHandle))
            {
                ProcessInput(glfw, winHandle);
            }
        }

        private unsafe void ProcessInput(Silk.NET.GLFW.Glfw glfw, Silk.NET.GLFW.WindowHandle* winHandle)
        {
            if (glfw.GetKey(winHandle, Silk.NET.GLFW.Keys.Escape) == (int)Silk.NET.GLFW.InputAction.Press)
                glfw.SetWindowShouldClose(winHandle, true);
        }

        #endregion

        // -----------

        private void FFLog(string str)
        {
            Logger.Info(str);
        }

        TimeSpan last;
        private void GlCtlOnRender(TimeSpan obj)
        {
            System.Diagnostics.Debug.WriteLine(obj);
        }

        int textureID;
        private void InitGL()
        {
            //textureID = OpenTK.Graphics.ES30.GL.GenTexture();
            //OpenTK.Graphics.ES30.GL.BindTexture(OpenTK.Graphics.ES30.TextureTarget.Texture2D, textureID);

            //int renderBuf = OpenTK.Graphics.ES30.GL.GenRenderbuffer();
            //OpenTK.Graphics.ES30.GL.BindTexture();
            //OpenTK.Graphics.Wgl.Wgl.DXRegisterObjectNV
        }

        private void GlCtlOnRenderAsync()
        {
            //OpenTK.Graphics.ES30.GL.Clear(OpenTK.Graphics.ES30.ClearBufferMask.ColorBufferBit);
        }

        private void OpenGLMediaPlayerClick(object sender, RoutedEventArgs e)
        {
            SilkOpenGLESUtils gles = new SilkOpenGLESUtils();
            gles.CreateWin(1280, 720);//"OpenGLWin"
            gles.Show();
        }
    }
}